#include <stdexcept>
#include <exception>
#include "JZJsonStream.h"
#include "assert.h"

JsonStream::JsonStream()
{
    parent = nullptr;
    read = true;
}

JsonStream::~JsonStream()
{
    Q_ASSERT(parent || m_subStream.size() == 0);
}

void JsonStream::close()
{
    if (m_subStream.size() == 0)
        return;

    QJsonObject obj = value.toObject();
    auto it = m_subStream.begin();
    while (it != m_subStream.end())
    {
        obj[it.key()] = it.value()->value;
        it++;
    }
    value = obj;

    qDeleteAll(m_subStream);
    m_subStream.clear();
}

JsonStream &JsonStream::operator[](const QString& member)
{
    if (m_subStream.contains(member))
        return *m_subStream[member];

    JsonStream* s = nullptr;
    if (read)
    {
        if(!value.isObject())
            throw JZException("value not object");

        auto obj = value.toObject();
        if(!obj.contains(member))
            throw JZException("no such member " + member);

        s = new JsonStream();
        s->value = obj[member];
    }
    else
    {
        s = new JsonStream();
        s->parent = this;
        s->read = false;
    }

    s->parent = this;
    m_subStream.insert(member, s);

    return *s;
}

void operator>>(JsonStream &s, bool& t)
{
    if (s.value.type() != QJsonValue::Bool)
    {
        throw JZException("type not bool");
    }
    t = s.value.toBool();
}

void operator<<(JsonStream& s, bool t)
{
    s.value = t;
}

//int16
void operator>>(JsonStream& s, int16_t& t)
{
    if (s.value.type() != QJsonValue::Double)
    {
        throw JZException("type not int");
    }
    t = s.value.toInt();
}

void operator<<(JsonStream& s, int16_t t)
{
    s.value = t;
}


void operator>>(JsonStream& s, uint16_t& t)
{
    if (s.value.type() != QJsonValue::Double)
    {
        throw JZException("type not int");
    }
    t = s.value.toInt();
}

void operator<<(JsonStream& s, uint16_t t)
{
    s.value = t;
}


void operator>>(JsonStream& s, int& t)
{
    if (s.value.type() != QJsonValue::Double)
    {
        throw JZException("type not int");
    }
    t = s.value.toInt();
}

void operator<<(JsonStream& s, int t)
{
    s.value = t;
}

void operator>>(JsonStream& s, uint32_t& t)
{
    if (s.value.type() != QJsonValue::Double)
    {
        throw JZException("type not int");
    }
    t = s.value.toInteger();
}

void operator<<(JsonStream& s, uint32_t t)
{
    s.value = (qint64)t;
}

void operator>>(JsonStream& s, int64_t& t)
{
    if (s.value.type() != QJsonValue::Double)
    {
        throw JZException("type not int");
    }
    t = s.value.toInteger();
}

void operator<<(JsonStream& s, int64_t t)
{
    s.value = t;
}

void operator>>(JsonStream& s, uint64_t& t)
{
    if (s.value.type() != QJsonValue::Double)
    {
        throw JZException("type not int");
    }
    t = s.value.toInteger();
}

void operator<<(JsonStream& s, uint64_t t)
{
    s.value = (qint64)t;
}

void operator>>(JsonStream& s, float& t)
{
    if (s.value.type() != QJsonValue::Double)
    {
        throw JZException("type not bool");
    }
    t = (float)s.value.toDouble();
}

void operator<<(JsonStream& s, float t)
{
    s.value = t;
}

void operator>>(JsonStream& s, double& t)
{
    if (s.value.type() != QJsonValue::Double)
    {
        throw JZException("type not double");
    }
    t = s.value.toDouble();
}

void operator<<(JsonStream& s, double t)
{
    s.value = t;
}

void operator>>(JsonStream& s, QString& t)
{
    if (s.value.type() != QJsonValue::String)
    {
        throw JZException("type not string");
    }
    t = s.value.toString();
}

void operator<<(JsonStream& s, const QString& t)
{
    s.value = t;
}